Windows access token 介绍及利用

1 背景

我第一次看到 windows access token 是在打靶场的时候,通过 msf 的工具获取主机上管理员用户的令牌来伪造管理员权限,并通过进程迁移实现完全的提权。

当时对于 windows access token 还有很多疑问,这里尝试对其机制进行一个比较完整的解释,以及总结一下如何利用这个 access token 进行用户的伪造。

.

.

2 Windows access token 机制介绍

一 简介

access token 翻译过来就是访问令牌,官方给的解释是:一个进程或者线程的描述安全上下文(the security context)的对象。安全上下文可以理解成一段关于系统安全的信息。

令牌中的信息包括与进程或线程相关的用户账户的身份和权限。

当用户登录系统之后,windows 会产生一个令牌(access token)颁发给用户,这是通过 LSASS.exe 这个程序完成的。

然后这个用户开启的所有进程都会从用户那里复制一份 access token 给进程自己。这也是为啥有时候 A 用户的进程 B 用户没有权限去使用,因为 A 、B 用户的 access token 不同,而且该进程的代码中写了令牌校验的机制。

当一个程序(线程)需要和系统安全相关的对象进行交互,或者需要权限执行某些系统任务的时候,windows 系统就会通过 access token 去校验身份。至于具体的校验机制,后面再补充。

.

二 令牌包含的内容

  • The security identifier (SID) for the user’s account
    • 用户帐户的安全标识符(SID)
  • SIDs for the groups of which the user is a member
    • 用户所属的组的SID
  • A logon SID that identifies the current logon session
    • 用于标识当前登录会话的登录SID
  • A list of the privileges held by either the user or the user’s groups
    • 用户或用户组所拥有的权限列表
  • An owner SID
    • 所有者SID
  • The SID for the primary group
    • 主要组的SID
  • The default DACL that the system uses when the user creates a securable object without specifying a security descriptor
    • 访问控制列表
  • The source of the access token
    • 访问令牌的来源
  • Whether the token is a primary or impersonation token
    • 令牌是主要令牌还是模拟令牌
  • An optional list of restricting SIDs
    • 限制SID的可选列表
  • Current impersonation levels
    • 目前的模拟等级
  • Other statistics
    • 其他统计数据

.

.

3 主要令牌和模拟令牌

一 主要令牌 (primary token)

1 主要令牌的产生

主要令牌是用户登录的时候系统就会给该用户先颁发一个主要令牌

这里的登录主要指交互式登录,比如本地登录,远程桌面

.

这里补充一下关于主要令牌产生的细节

用户使用凭据(用户密码)进行认证 –> 登录 session 创建 –> windows 返回用户的 sid 和用户所在组的 sid –> LSA 创建一个 Access token —> 使用凭据成功认证 –> 登录 session —> token —> 进程、线程

image-20220208160257180

.

2 主要令牌的传递

用户登录之后,用户开启的所有进程都会先复制一份主要令牌给进程自己

因此每个进程都有一个主要令牌,用于描述与该进程关联的用户帐户的安全上下文。

默认情况下,当进程的线程与安全对象进行交互时,系统使用主令牌。

此外,主要令牌有个机制,前面我们说了每个进程都复制了一份创建者的主要令牌,而这些进程开启的子进程也会从父进程那继承一份主要令牌(前提是子进程的代码中没有指定使用特定的 access token,且这个过程还是有 LSASS.exe 执行的)

.

二 模拟令牌(impersonation token)

1 模拟令牌的定义

主要令牌很好理解,就是用户登录后系统颁发的描述安全信息的对象

而模拟令牌的定义则是:

当进程(线程)需要以其他用户的身份获取系统资源或执行某些功能的时候,就需要用到其他用户的模拟令牌

impersonation tokens: these allow a particular process(or thread in a process) to gain access to resources using the token of another (user/client) process

注意:一个模拟其他用户(客户端)的进程或线程是同时具有自己的主令牌和其他用户的模拟令牌的

.

2 模拟令牌的产生

当用户注销后,系统将会使主令牌切换为模拟令牌并保存在系统中,

且不会将令牌清除,只有在重启机器后才会清除。

.

3 为什么会有模拟令牌?(我们拿模拟令牌来干嘛)

impersonation token is for impersonation .(模拟令牌是用来模拟的)

看起来像句废话,但是这里重点在于 模拟(impersonation) 这个行为

官方原文:

Impersonation is the ability of a thread to execute using different security information than the process that owns the thread. Typically, a thread in a server application impersonates a client. This allows the server thread to act on behalf of that client to access objects on the server or validate access to the client’s own objects.

大概意思是,线程有时候要使用到其他用户的安全信息时,就会需要到模拟令牌。模拟(impersonation)就是去线程去模拟其他用户的身份,从而可以更加方便地执行各种功能逻辑。

简单来说就是我们希望不同用户(客户端)来访问主机上的服务时,服务可以模拟客户端的身份去访问服务,而不是用自己的主进程Token身份去访问,从而解决一些权限问题。

.

4 模拟令牌的级别

我们说用户注销之后会产生模拟令牌,且模拟令牌的意义就是用来被线程模拟其他用户身份的,但是并不是所有的用户都想被线程模拟身份。

所以模拟令牌就设置了一个级别机制

只有当模拟令牌具有 Impersonation 和 Delegation 级别的时候才可以被用来模拟。

.

模拟令牌的所有级别:

  • SecurityAnonymous:current user/client cannot impersonate another user/client
    • 其他用户(客户端)无法通过这个模拟令牌模拟该用户(模拟令牌的所有者)或者客户端。
  • SecurityIdentification:current user/client can get the identity and privileges of a client, but cannot impersonate the client
    • 其他用户(客户端)可以通过这个模拟令牌获取到该用户的身份信息和权限,但是不能伪造该用户(客户端)
  • SecurityImpersonation:current user/client can impersonate the client’s security context on the local system
    • 其他用户可以在本地系统上通过这个模拟令牌伪造该用户,伪造指的是获取到该用户的安全上下文
  • SecurityDelegation:current user/client can impersonate the client’s security context on a remote system
    • 其他用户可以在远程系统上通过这个模拟令牌伪造该用户

.

.

4 不同登录方式获取的令牌

一 登录方式

  • 交互式登录
    • console login (type 2)
    • rdp login (type 10)
    • psexec (type 2)
  • 网络登录
    • wmi (type 3)
    • winrm (type 3)

.

二 各自获取的令牌种类

  • primary token 这种令牌通常用于本地及远程 RDP 登录

  • impersonation token 这种则通常用于各种非交互式的登录,比如,netuse,wmi,winrm等等

.

.

5 盗取模拟令牌攻击 (Token Kidnapping)

一 原理

经过上面的介绍,

我们知道了用户注销的时候会在系统上保存一个模拟令牌,而在特定情况下,当前用户(进程)又可以使用模拟令牌来伪造模拟令牌所属者的身份。

所以这里就存在一个提权的可能。

假设现在拿到主机的一个普通用户 Normal 的权限

只要满足下面几点条件,就能够通过盗取管理员用户的模拟令牌来实现提权

  • Normal 用户拥有 SeImpersonatePrivilege 权限,这意味着该用户能够使用别人的模拟令牌
  • 管理员用户注销之后,系统并没有重启,此时管理员的模拟令牌仍保留在系统上
  • 管理员的模拟令牌的等级是 SecurityDelegation (远程)或者 SecurityImpersonation(本地)

.

不过需要注意的是,有时候盗取管理员令牌之后,仍不算百分百的提权。还需要进行进程迁移才能够实现百分百提提权。

关于这点我没有找到特别明确的解释,以下的解释只是个人理解

首先用户登录的时候,系统会给当前用户颁发 primary token (主要令牌),然后该用户开启的所有进程都会复制一份这个 token 给进程自己。

而当用户注销后,系统将会使主令牌切换为模拟令牌,并保存在系统上。系统此时不会将令牌清除,只
有在重启机器后才会清除。

所以我们只要能够拿到保存在系统上的其他用户的模拟令牌(impersonation token),就能够对该用户
进行一定程度上的伪造。
为啥说是一定程度,而不是完全伪造呢?

因为有的进程是认模拟令牌(impersonation token)的,所以对于这些进程,只要有模拟令牌,就会被进程认为当前用户是合法的,并允许当前用户使用该进程。

但并不是所有的进程都认,有很多进程只认 primary token(主要令牌),所以只有模拟令牌的话,并不能算完全伪造目标用户。

后续如果要完全模拟的话,还是需要进行进程迁移。

由于进程有个机制,在进程被创建的时候,如果代码没有写明要指定获取某个特定的令牌,那么该进程就会从父进程那里继承父进程的令牌。

所以,只要我们能够进程迁移到拥有目标用户主要令牌的进程上,我们就能通过主要令牌完全伪造目标用户了。

.

.

二 实战 (取自 tryhackme Alfred 部分靶场笔记)

这里使用 tryhackme 的 Alfred 靶场进行演示,

当我们拿到一个 meterpreter session , sessions -i 1 连上

getuid 命令查看下当前用户,发现是普通用户 alfred\bruce

image-20220208171226852

然后在 meterpreter shell 中打开一个 cmd 命令行 shell

接下来查看当前用户的权限,看看是否有 SeImpersonatePrivilege 权限whoami /priv 命令)

image-20220125155510832

.

发现的确存在,那么当前用户就可以使用系统中保存的其他用户的模拟令牌

接下来退出 cmd shell ,并使用 msf 中的 incognito 模块尝试列举都有什么用户的模拟令牌

load incognito 加载 incognito 模块

list_tokens -g 列举系统保存了什么用户的模拟令牌

image-20220125172816401

image-20220125172843607

可以看到,

使用 list_tokens -g 命令列举系统保存了什么模拟令牌之后,

出现了两个表,

Impersonation Tokens Availlable 和

Delegation Tokens Available

其实他们都是模拟令牌,只不过级别不一样。

Delegation 是最高级别,允许当前用户在远程系统上来使用这个模拟令牌

我们主要查看 Delegation 中的模拟令牌,因为是远程连接进去的

恰好这里有一个属于管理员的模拟令牌

用它!

使用如下命令

impersonate_token “指定的用户” 拿取制定用户的模拟令牌

impersonate_token “BUILTIN\Administrators” 拿取 Administrators 的 impersonation token

image-20220125182701837

.

成功拿到管理员的模拟令牌之后

此时使用 getuid 命令,查看当前用户是不是管理员

image-20220125182900616

可以看到,确实显示的是管理员

但是即使是现在,我们拿到了管理员的模拟令牌,也不一定能够完全伪造管理员的身份

就像之前说的那样,有些进程通过 impersonation token (模拟令牌) 来认当前用户身份,

而有些进程只认 primary token (主要令牌) 来确认用户的身份

所以我们需要进行进程迁移

.

那么现在的情况是,我们只是通过拿取模拟令牌实现了一定程度上的伪造管理员用户

接下来就是通过进程迁移,迁移到拥有管理员用户的主要令牌的进程

通过进程会继承父进程主要令牌的机制,完全伪造管理员

实现百分百的提权

这里推荐一个最保险的进程,services.exe

.

先用 ps 命令查看进程:

image-20220125185603130

.

migrate 668 迁移到 services.exe 去

image-20220125203947224

此时已经拿到了管理员的主要令牌了,

已经可以百分百伪造管理员了

接下来为了进一步确认,尝试去读取靶标 (C:\Windows\System32\config\root.txt)

.

开启一个 cmd shell

type C:\Windows\System32\config\root.txt

即可成功读取到靶标

image-20220125204530203

.

.

6 参考文章

https://www.anquanke.com/post/id/204721

https://hackergu.com/powerup-stealtoken-rottenpotato/

https://docs.microsoft.com/en-us/windows/win32/secauthz/access-tokens

https://docs.microsoft.com/en-us/windows/win32/secauthz/client-server-access-control

https://docs.microsoft.com/en-us/windows/win32/secauthz/impersonation-levels

https://rootclay.gitbook.io/windows-access-control/access-token

https://www.anquanke.com/post/id/204721

https://msrc-blog.microsoft.com/2009/04/14/token-kidnapping/

http://www.4k8k.xyz/article/qq_41874930/111963586

https://www.offensive-security.com/metasploit-unleashed/fun-incognito/

https://payloads.online/archivers/2018-11-30/1/#0x03-windows-access-token

https://www.exploit-db.com/papers/42556

https://lengjibo.github.io/token/

https://www.geekby.site/2020/05/域渗透之-windows-access-token-攻击/

https://shanfenglan.blog.csdn.net/article/details/111926058

https://3gstudent.github.io/渗透技巧-Windows九种权限的利用

https://blog.csdn.net/sch0120/article/details/70226903

.

.

/